from fastapi import APIRouter, HTTPException, Depends
from sqlalchemy.exc import SQLAlchemyError

from db.controller.db_controller import db_controller
from db.model.enums import DeviceType
from enums.protocol_type import ProtocolType
from web.dependencies import get_server_manager
from web.log import log
from web.model.device import CreateDevice, EditDevice, DeviceName

# 创建路由对象
device_router = APIRouter()


@device_router.post('/add_device')
async def add_device(body: CreateDevice, server_manager=Depends(get_server_manager)):
    device_name = body.device_name
    ip = body.ip
    port = body.port
    protocol = body.protocol
    try:
        if protocol == ProtocolType.TCP:
            db_controller.device_dao.add_device(device_type=DeviceType.TCP, device_name=device_name, ip=ip, port=port,
                                                protocol=protocol)
            server_manager.add_modbus_tcp_client(device_name, ip, port)
        elif protocol == ProtocolType.RTU_OVER_TCP:
            db_controller.device_dao.add_device(device_type=DeviceType.RTU_OVER_TCP, device_name=device_name, ip=ip,
                                                port=port, protocol=protocol)
            server_manager.add_modbus_rtu_over_tcp_client(device_name, ip, port)
        else:
            raise HTTPException(status_code=500, detail={'status': 500, 'msg': '添加设备失败', 'data': False})
        return {'status': 200, 'msg': '添加设备成功', 'data': True}
    except SQLAlchemyError as e:
        log.error(f"数据库操作失败: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'数据库错误: {e}', 'data': False})
    except Exception as e:
        log.error(f"未知错误: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'服务器内部错误: {e}', 'data': False})


@device_router.post('/edit_device')
async def edit_device(body: EditDevice, server_manager=Depends(get_server_manager)):
    device_id = body.device_id
    device_name = body.device_name
    ip = body.ip
    port = body.port
    protocol = body.protocol
    try:
        old_device = db_controller.device_dao.get_device_by_id(device_id)
        old_device_name = old_device.get('name')

        if protocol == ProtocolType.TCP:
            db_controller.device_dao.edit_device(DeviceType.TCP, device_id, device_name, ip, port, protocol)
            server_manager.edit_client(old_device_name, device_name, protocol, ip, port)
        elif protocol == ProtocolType.RTU_OVER_TCP:
            db_controller.device_dao.edit_device(DeviceType.RTU_OVER_TCP, device_id, device_name, ip, port, protocol)
            server_manager.edit_client(old_device_name, device_name, protocol, ip, port)
        else:
            raise HTTPException(status_code=500, detail={'status': 500, 'msg': '修改设备失败', 'data': False})
        return {'status': 200, 'msg': '修改设备成功', 'data': True}
    except SQLAlchemyError as e:
        log.error(f"数据库操作失败: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'数据库错误: {e}', 'data': False})
    except Exception as e:
        log.error(f"未知错误: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'服务器内部错误: {e}', 'data': False})


@device_router.post('/delete_device')
async def delete_device(body: DeviceName, server_manager=Depends(get_server_manager)):
    device_name = body.device_name
    try:
        if db_controller.device_dao.delete_device(device_name):
            server_manager.delete_client(device_name)
            return {'status': 200, 'msg': '删除设备成功', 'data': True}
        else:
            raise HTTPException(status_code=500, detail={'status': 500, 'msg': '删除设备失败', 'data': False})
    except SQLAlchemyError as e:
        log.error(f"数据库操作失败: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'数据库错误: {e}', 'data': False})
    except Exception as e:
        log.error(f"未知错误: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'服务器内部错误: {e}', 'data': False})


@device_router.get('/get_device_list')
async def get_device_list():
    try:
        device_list = db_controller.device_dao.get_device_list()
        return {'status': 200, 'msg': '获取设备列表成功!', 'data': device_list}
    except Exception as e:
        log.error(e)
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'服务器内部错误: {e}!', 'data': True})


@device_router.post('/open_connection')
async def open_connection(body: DeviceName, server_manager=Depends(get_server_manager)):
    device_name = body.device_name
    try:
        if server_manager.start_server(device_name):
            return {'status': 200, 'msg': '打开连接成功', 'data': True}
        else:
            return {'status': 500, 'msg': '打开连接失败, 设备已经在运行中', 'data': False}
    except Exception as e:
        log.error(f"打开连接失败: {str(e)}")
        raise HTTPException(status_code=500,
                            detail={'status': 500, 'msg': f'打开连接失败, 错误信息: {e}', 'data': False})


@device_router.post('/close_connection')
async def close_connection(body: DeviceName, server_manager=Depends(get_server_manager)):
    device_name = body.device_name
    try:
        if server_manager.stop_server(device_name):
            return {'status': 200, 'msg': '关闭连接成功', 'data': True}
        else:
            raise HTTPException(status_code=500,
                                detail={'status': 500, 'msg': '关闭连接失败, 设备不存在', 'data': False})
    except Exception as e:
        log.error(f"关闭连接失败: {str(e)}")
        raise HTTPException(status_code=500,
                            detail={'status': 500, 'msg': f'关闭连接失败, 错误信息: {e}', 'data': False})


@device_router.post('/get_latest_message')
async def get_latest_message(body: DeviceName, server_manager=Depends(get_server_manager)):
    device_name = body.device_name
    try:
        server = server_manager.get_server(device_name)
        if server:
            message = server.get_latest_message()
            return {'status': 200, 'msg': '获取最新报文成功!', 'data': message}
        else:
            raise HTTPException(status_code=500,
                                detail={'status': 500, 'msg': '获取最新报文失败, 设备不存在!', 'data': []})
    except Exception as e:
        log.error(e)
        raise HTTPException(status_code=500,
                            detail={'status': 500, 'msg': f'获取最新报文失败, 服务器内部错误 {e}!', 'data': []})
